#include "widget.h"
#include "./ui_widget.h"

// 样式表
/* 悬停样式  按下样式 */
#define styleBtnTopY ("QPushButton#btnTop{background-color: #ffb855}" \
                      "QPushButton#btnTop:pressed{background-color: #E7E7E7;}")
#define styleBtnTopN ("QPushButton#btnTop:hover{background-color: #E1E1E1;}" \
                      "QPushButton#btnTop:pressed{background-color: #E7E7E7;}")
#define styleBtnMinSize ("QPushButton#btnMinSize:hover{background-color: #E1E1E1;}" \
                         "QPushButton#btnMinSize:pressed{background-color: #E7E7E7;}")
#define styleBtnMaxSize ("QPushButton#btnMaxSize:hover{background-color: #E1E1E1;}" \
                         "QPushButton#btnMaxSize:pressed{background-color: #E7E7E7;}")
#define styleBtnExit(radius) ("QPushButton#btnExit{border-top-right-radius:" +        \
                              QString::number(radius) + "px; }" +                     \
                              "QPushButton#btnExit:hover{background-color: #E81123;}" \
                              "QPushButton#btnExit:pressed{background-color: #971721;}")
/* 窗口以及按钮背景颜色  窗口背景为圆角  无边框  标题栏横线  第二个主窗口底部为圆角 */
#define styleWidget(radius) ("#widget, QPushButton{background-color: #F3F3F3;}"          \
                             "#widget{border-radius:" +                                  \
                             QString::number(radius) + "px}" +                           \
                             "#widget, #windowWidget, QPushButton{border: none}" +       \
                             "#windowWidget{border-top: 1px solid rgb(154, 154, 154)}" + \
                             "#windowWidget{border-radius: 0px 0px " + QString::number(radius) + "px " + QString::number(radius) + "px}")

Widget::Widget(QWidget *parent)
    : QWidget(parent), ui(new Ui::Widget)
{
    ui->setupUi(this);

    // 关闭QT边框
    setWindowFlag(Qt::FramelessWindowHint);
    // 设置窗口透明
    setAttribute(Qt::WA_TranslucentBackground);
    // 启用鼠标跟踪
    setMouseTracking(true);
    // 设置事件过滤器---进入主窗口区域---标题栏拖动
    ui->windowWidget->installEventFilter(this);
    ui->title->installEventFilter(this);
    ui->btnExit->installEventFilter(this);
    ui->btnMaxSize->installEventFilter(this);
    ui->btnMinSize->installEventFilter(this);
    ui->btnTop->installEventFilter(this);

    // 设置按钮样式
    ui->btnMinSize->setStyleSheet(styleBtnMinSize);
    ui->btnMaxSize->setStyleSheet(styleBtnMaxSize);
    ui->btnExit->setStyleSheet(styleBtnExit(borderRadius));
    ui->btnTop->setStyleSheet(styleBtnTopN);
    // 设置窗口样式
    ui->widget->setStyleSheet(styleWidget(borderRadius));
    // 设置窗口边框宽度
    ui->widgetLayout->setContentsMargins(borderWidth, borderWidth, borderWidth, borderWidth);

    // 置顶按钮
    // 使用 windows.h 微软平台库，造成无法跨平台---优点：切换时不闪屏
    // 使用 Qt 库 Qt::WindowStaysOnTopHint 切换时会闪屏
    connect(ui->btnTop, &QPushButton::clicked, this, [=]()
    {
        if (m_isTopWidget)
        {
            m_isTopWidget = false;
            // 取消置顶
            // setWindowFlag(Qt::WindowStaysOnTopHint, false);
            SetWindowPos(reinterpret_cast<HWND>(winId()), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            ui->btnTop->setStyleSheet(styleBtnTopN);
        }
        else
        {
            m_isTopWidget = true;
            // 置顶
            // setWindowFlag(Qt::WindowStaysOnTopHint);
            SetWindowPos(reinterpret_cast<HWND>(winId()), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
            ui->btnTop->setStyleSheet(styleBtnTopY);
        }
        // show();
    });
    // 最大化、还原页面按钮
    connect(ui->btnMaxSize, &QPushButton::clicked, this, [=]()
    {
        if (!isMaximized())
        {
            // 最大化---边框无圆角-圆角半径为 0px
            ui->widget->setStyleSheet(styleWidget(0));
            ui->widgetLayout->setContentsMargins(0, 0, 0, 0); // 设置窗口边框为 0px
            // 按钮样式---右上角关闭按钮无圆角 0px
            ui->btnMaxSize->setIcon(QIcon(":/Icons/minimize.svg"));
            ui->btnExit->setStyleSheet(styleBtnExit(0));
            // 最大化
            showMaximized();
        }
        else
        {
            // 还原---边框圆角-圆角半径为 borderRadius
            // 设置窗口样式
            ui->widget->setStyleSheet(styleWidget(borderRadius));
            // 设置窗口边框宽度
            ui->widgetLayout->setContentsMargins(borderWidth, borderWidth, borderWidth, borderWidth);
            // 按钮样式---右上角关闭按钮有圆角 borderRadius
            ui->btnMaxSize->setIcon(QIcon(":/Icons/maximize.svg"));
            ui->btnExit->setStyleSheet(styleBtnExit(borderRadius));
            // 原窗口
            showNormal();
        }
    });
    // 最小化窗口按钮
    connect(ui->btnMinSize, &QPushButton::clicked, this, &Widget::showMinimized);
    // 关闭窗口按钮
    connect(ui->btnExit, &QPushButton::clicked, this, &Widget::close);
}

// 重写绘画事件
void Widget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing, true); // 抗锯齿
    QColor color(0, 0, 0, 0);
    // 边框阴影
    for (int i = 0; i < borderWidth; i++)
    {
        QPainterPath path;
        path.addRoundedRect(i, i, width() - i * 2, height() - i * 2, borderRadius, borderRadius);
        color.setAlphaF(0.3 * pow(i + 1, 2) / borderWidth / borderWidth);
        painter.setPen(color);
        painter.drawPath(path);
    }
}

// 重写鼠标按下事件
void Widget::mousePressEvent(QMouseEvent *event)
{
    // 鼠标按下事件
    if (event->button() == Qt::LeftButton && m_resizeDirection != direction::none)
    {
        // 改变窗口 或者 移动窗口
        m_clickPos = event->globalPosition();
        m_leftTop = frameGeometry().topLeft();
        m_leftBottom = frameGeometry().bottomLeft();
        m_rightTop = frameGeometry().topRight();

        m_isChangeWidget = true;

        // qDebug() << m_clickPos << m_leftTop << m_leftBottom << m_rightTop;
    }
    QWidget::mousePressEvent(event);
}

// 重写鼠标释放事件
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton)
        m_isChangeWidget = false;
    QWidget::mouseReleaseEvent(event);
}

// 重写鼠标移动事件---只追踪了边框区域
void Widget::mouseMoveEvent(QMouseEvent *event)
{
    // qDebug() << event->pos();
    //  主体区域
    QRect mainRect(borderWidth + borderRadius, borderWidth, width() - 2 * borderWidth - 2 * borderRadius, height() - 2 * borderWidth);
    // 在边框区域 且 不是在改变窗口状态
    if (!mainRect.contains(event->pos()) && !m_isChangeWidget && event->buttons() == Qt::NoButton)
    {
        // 在窗口边界区域内
        if (event->pos().x() < borderWidth + borderRadius && event->pos().y() < borderWidth + borderRadius)
        {
            // 左上角
            m_resizeDirection = direction::left_top;
            setCursor(Qt::SizeFDiagCursor);
        }
        else if (event->pos().x() < borderWidth + borderRadius && event->pos().y() > height() - borderWidth - borderRadius)
        {
            // 左下角
            m_resizeDirection = direction::left_bottom;
            setCursor(Qt::SizeBDiagCursor);
        }
        else if (event->pos().x() > width() - borderWidth - borderRadius && event->pos().y() < borderWidth + borderRadius)
        {
            // 右上角
            m_resizeDirection = direction::right_top;
            setCursor(Qt::SizeBDiagCursor);
        }
        else if (event->pos().x() > width() - borderWidth - borderRadius && event->pos().y() > height() - borderWidth - borderRadius)
        {
            // 右下角
            m_resizeDirection = direction::right_bottom;
            setCursor(Qt::SizeFDiagCursor);
        }
        else if (event->pos().x() < borderWidth)
        {
            // 左边
            m_resizeDirection = direction::left;
            setCursor(Qt::SizeHorCursor);
        }
        else if (event->pos().x() >= width() - borderWidth)
        {
            // 右边
            m_resizeDirection = direction::right;
            setCursor(Qt::SizeHorCursor);
        }
        else if (event->pos().y() < borderWidth)
        {
            // 上边
            m_resizeDirection = direction::top;
            setCursor(Qt::SizeVerCursor);
        }
        else if (event->pos().y() >= height() - borderWidth)
        {
            // 下边
            m_resizeDirection = direction::bottom;
            setCursor(Qt::SizeVerCursor);
        }
        else
        {
            // 无
            m_resizeDirection = direction::none;
            setCursor(Qt::ArrowCursor);
        }
    }
    // 改变窗口状态
    if (event->buttons() == Qt::LeftButton && m_isChangeWidget)
    {
        switch (m_resizeDirection)
        {
        case direction::left_top:
        {
            int dx = m_clickPos.x() - event->globalPosition().x();                                                                   // 改变量
            dx = dx + m_rightTop.x() - m_leftTop.x() >= minimumWidth() ? dx : minimumWidth() - m_rightTop.x() + m_leftTop.x();       // 限制
            int new_x = m_leftTop.x() - dx;                                                                                          // 新的x坐标
            int dy = m_clickPos.y() - event->globalPosition().y();                                                                   // 改变量
            dy = dy + m_leftBottom.y() - m_leftTop.y() >= minimumHeight() ? dy : minimumHeight() - m_leftBottom.y() + m_leftTop.y(); // 限制
            int new_y = m_leftTop.y() - dy;                                                                                          // 新的y坐标
            setGeometry(new_x, new_y, dx + m_rightTop.x() - m_leftTop.x(), dy + m_leftBottom.y() - m_leftTop.y());
            update();
            break;
        }
        case direction::left_bottom:
        {
            int dx = m_clickPos.x() - event->globalPosition().x();                                                             // 改变量
            dx = dx + m_rightTop.x() - m_leftTop.x() >= minimumWidth() ? dx : minimumWidth() - m_rightTop.x() + m_leftTop.x(); // 限制
            int new_x = m_leftTop.x() - dx;                                                                                    // 新的x坐标
            int dy = event->globalPosition().y() - m_clickPos.y();                                                             // 改变量
            setGeometry(new_x, m_leftTop.y(), dx + m_rightTop.x() - m_leftTop.x(), dy + m_leftBottom.y() - m_leftTop.y());
            update();
            break;
        }
        case direction::right_top:
        {
            int dx = event->globalPosition().x() - m_clickPos.x();                                                                   // 改变量
            int dy = m_clickPos.y() - event->globalPosition().y();                                                                   // 改变量
            dy = dy + m_leftBottom.y() - m_leftTop.y() >= minimumHeight() ? dy : minimumHeight() - m_leftBottom.y() + m_leftTop.y(); // 限制
            int new_y = m_leftTop.y() - dy;                                                                                          // 新的y坐标
            setGeometry(m_leftTop.x(), new_y, dx + m_rightTop.x() - m_leftTop.x(), dy + m_leftBottom.y() - m_leftTop.y());
            update();
            break;
        }
        case direction::right_bottom:
        {
            int dx = event->globalPosition().x() - m_clickPos.x(); // 改变量
            int dy = event->globalPosition().y() - m_clickPos.y(); // 改变量
            resize(dx + m_rightTop.x() - m_leftTop.x(), dy + m_leftBottom.y() - m_leftTop.y());
            update();
            break;
        }
        case direction::left:
        {
            int dx = m_clickPos.x() - event->globalPosition().x();                                                             // 改变量
            dx = dx + m_rightTop.x() - m_leftTop.x() >= minimumWidth() ? dx : minimumWidth() - m_rightTop.x() + m_leftTop.x(); // 限制
            int new_x = m_leftTop.x() - dx;                                                                                    // 新的x坐标
            setGeometry(new_x, m_leftTop.y(), dx + m_rightTop.x() - m_leftTop.x(), height());
            update();
            break;
        }
        case direction::right:
        {
            int dx = event->globalPosition().x() - m_clickPos.x(); // 改变量
            resize(dx + m_rightTop.x() - m_leftTop.x(), height());
            update();
            break;
        }
        case direction::top:
        {
            int dy = m_clickPos.y() - event->globalPosition().y();                                                                   // 改变量
            dy = dy + m_leftBottom.y() - m_leftTop.y() >= minimumHeight() ? dy : minimumHeight() - m_leftBottom.y() + m_leftTop.y(); // 限制
            int new_y = m_leftTop.y() - dy;                                                                                          // 新的y坐标
            setGeometry(m_leftTop.x(), new_y, width(), dy + m_leftBottom.y() - m_leftTop.y());
            update();
            break;
        }
        case direction::bottom:
        {
            int dy = event->globalPosition().y() - m_clickPos.y(); // 改变量
            resize(width(), dy + m_leftBottom.y() - m_leftTop.y());
            update();
            break;
        }
        case direction::move_widget:
        {
            if (isMaximized())
            {
                // 最大化状态下移动窗口
                QRect normalRect = normalGeometry();
                // 新x坐标点
                int new_x = m_clickPos.x() - (((m_clickPos.x() - m_leftTop.x()) * 1.0 / width()) * normalRect.width());
                int new_y = event->globalPosition().y() - m_clickPos.y() + m_leftTop.y() - borderWidth;
                // 显示界面原始大小
                setGeometry(new_x, new_y, normalRect.width(), normalRect.height());
                // 更新参数
                m_clickPos = event->globalPosition();
                m_leftTop = QPointF(new_x, new_y);
                // 更新样式
                ui->widget->setStyleSheet(styleWidget(borderRadius));
                ui->widgetLayout->setContentsMargins(borderWidth, borderWidth, borderWidth, borderWidth);
                ui->btnMaxSize->setIcon(QIcon(":/Icons/maximize.svg"));
                ui->btnExit->setStyleSheet(styleBtnExit(borderRadius));
                update();
                break;
            }
            QPointF newPos = event->globalPosition() - m_clickPos + m_leftTop;
            move(newPos.toPoint()); // 移动窗口到新位置
            break;
        }
        default:
            break;
        }
    }

    QWidget::mouseMoveEvent(event);
}

// 重写事件过滤器---鼠标进入主窗口区域 不执行窗口大小改变
bool Widget::eventFilter(QObject *watched, QEvent *event)
{
    if (watched == ui->windowWidget)
    {
        if (event->type() == QEvent::Enter)
        {
            // 鼠标进入主窗口
            m_resizeDirection = direction::none;
            setCursor(Qt::ArrowCursor);
        }
    }
    else if (watched == ui->title)
    {
        if (event->type() == QEvent::Enter)
        {
            // 鼠标进入标题栏---可移动窗口
            m_resizeDirection = direction::move_widget;
            setCursor(Qt::SizeAllCursor);
        }
        else if (event->type() == QEvent::Leave)
        {
            // 鼠标移出标题栏---不可移动
            m_resizeDirection = direction::none;
            setCursor(Qt::ArrowCursor);
        }
        else if (event->type() == QEvent::MouseButtonDblClick)
        {
            // 双击标题栏
            ui->btnMaxSize->click();
        }
    }
    else if (watched == ui->btnExit || watched == ui->btnMaxSize || watched == ui->btnMinSize || watched == ui->btnTop)
    {
        if (event->type() == QEvent::Enter)
        {
            // 鼠标进入按钮---恢复原状态
            m_resizeDirection = direction::none;
            setCursor(Qt::ArrowCursor);
        }
    }
    return QWidget::eventFilter(watched, event);
}

// 析构函数
Widget::~Widget()
{
    delete ui;
}
